#include "GtsFile.hpp"
#include "Mesh.hpp"
#include <vector>
#include <sstream>
#include <vector>
#include <map>
#include <fstream>
using namespace std;

namespace
{
   typedef std::map<Edge, int> EdgeMap;
   typedef std::vector<Edge> EdgeList;
   void InsertEdge(int a, int b, EdgeMap& aMap, EdgeList& aList)
   {
      Edge e = OrderEdge(a,b);
      if (aMap.find(e) == aMap.end())
      {
         aMap.insert(EdgeMap::value_type(e, aList.size()));
         aList.push_back(e);
      }
   }
}

void GtsFile::Write(const std::string& aFileName,
                    Mesh&              aMesh)
{
   ofstream file(aFileName.c_str());
   file << aMesh.verts.size() << ' ';
   
   std::map<Edge, int> edgeIndices;
   std::vector<Edge> edges;
   for (size_t i = 0; i < aMesh.faces.size(); ++i)
   {
      Face& f = aMesh.faces[i];
      InsertEdge(f.vertex[0], f.vertex[1], edgeIndices, edges);
      InsertEdge(f.vertex[1], f.vertex[2], edgeIndices, edges);
      InsertEdge(f.vertex[2], f.vertex[0], edgeIndices, edges);
   }
   file << edges.size() << ' ' << aMesh.faces.size() << " GtsSurface GtsFace GtsEdge GtsVertex\n";

   for (size_t i = 0; i < aMesh.verts.size(); ++i)
   {
      Vec3& v = aMesh.verts[i];
      file << v.x << ' ' << v.y << ' ' << v.z << '\n';
   }

   for (size_t i = 0; i < edges.size(); ++i)
   {
      file << edges[i].first + 1 << ' ' << edges[i].second + 1 << '\n';
   }

   for (size_t i = 0; i < aMesh.faces.size(); ++i)
   {
      Face& f = aMesh.faces[i];
      Edge e1 = OrderEdge(f.vertex[0], f.vertex[1]);
      Edge e2 = OrderEdge(f.vertex[1], f.vertex[2]);
      Edge e3 = OrderEdge(f.vertex[2], f.vertex[0]);
      file << edgeIndices[e1] + 1 << ' ' << edgeIndices[e2] + 1 << ' ' << edgeIndices[e3] + 1 << '\n';
   }
}
//
//
//void GtsFile::Read(const std::string& aFileName,
//                   Mesh&              aMesh)
//{
//   ifstream file(aFileName.c_str());
//   int vertCount, edgeCount, faceCount;
//   file >> vertCount >> edgeCount >> faceCount;
//   file.ignore(999, '\n');
//   
//   // read vertices
//   char line[256];
//   while (file.getline(line, 255))
//   {
//      if (line[0] == '#') continue;
//      if (vertCount-- == 0) break;
//      Vec3 v;
//      stringstream ss(line);
//      ss >> v.x >> v.y >> v.z;
//      aMesh.verts.push_back(v);
//   }
//
//   // read edges
//   std::vector<Edge> edges;
//   while (file.getline(line, 255))
//   {
//      if (line[0] == '#') continue;
//      if (edgeCount-- == 0) break;
//      Edge e;
//      stringstream ss(line);
//      ss >> e.first >> e.second;
//      edges.push_back(e);
//   }
//
//   // read faces
//   std::vector<Face> faces;
//   while (file.getline(line, 255))
//   {
//      if (line[0] == '#') continue;
//      if (faceCount-- == 0) break;
//      Face f;
//      stringstream ss(line);
//      int e1, e2, e3;
//      ss >> f.vertex[0] >> f.vertex[1] >> f.vertex[2];
//      faces.push_back(f);
//   }
//
//   std::map<Edge, int> edgeIndices;
//   for (size_t i = 0; i < aMesh.faces.size(); ++i)
//   {
//      Face& f = aMesh.faces[i];
//      InsertEdge(f.vertex[0], f.vertex[1], edgeIndices, edges);
//      InsertEdge(f.vertex[1], f.vertex[2], edgeIndices, edges);
//      InsertEdge(f.vertex[2], f.vertex[0], edgeIndices, edges);
//   }
//   file << edges.size() << ' ' << aMesh.faces.size() << " GtsSurface GtsFace GtsEdge GtsVertex\n";
//
//   for (size_t i = 0; i < aMesh.verts.size(); ++i)
//   {
//      Vec3& v = aMesh.verts[i];
//      file << v.x << ' ' << v.y << ' ' << v.z << '\n';
//   }
//
//   for (size_t i = 0; i < edges.size(); ++i)
//   {
//      file << edges[i].first + 1 << ' ' << edges[i].second + 1 << '\n';
//   }
//
//   for (size_t i = 0; i < aMesh.faces.size(); ++i)
//   {
//      Face& f = aMesh.faces[i];
//      Edge e1 = OrderEdge(f.vertex[0], f.vertex[1]);
//      Edge e2 = OrderEdge(f.vertex[1], f.vertex[2]);
//      Edge e3 = OrderEdge(f.vertex[2], f.vertex[0]);
//      file << edgeIndices[e1] + 1 << ' ' << edgeIndices[e2] + 1 << ' ' << edgeIndices[e3] + 1 << '\n';
//   }
//}
